/*
 ============================================================================
 Name		: DocXmlParser.cpp
 Author	  : JohnLZeng
 Version	 : 1.0
 Copyright   : Your copyright notice
 Description : CDocXmlParser implementation
 ============================================================================
 */

#include "DocXmlParser.h"

#include "MacroUtil.h"
#include "CommonUtils.h"
#include <txtetext.h>
#include <f32file.h>
#include <CoeMain.h>
#include "RSSBriefData.h"
#include "CommonFileUtil.h"

CDocXmlParser::CDocXmlParser()
	{
	// No implementation required
	}

CDocXmlParser::~CDocXmlParser()
	{
	Clear();

	iTagStack.Close();
	}

CDocXmlParser* CDocXmlParser::NewLC()
	{
	CDocXmlParser* self = new (ELeave) CDocXmlParser();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CDocXmlParser* CDocXmlParser::NewL()
	{
	CDocXmlParser* self = CDocXmlParser::NewLC();
	CleanupStack::Pop(); // self;
	return self;
	}

void CDocXmlParser::ConstructL()
	{
	}

void CDocXmlParser::Clear()
	{
	iTagStack.Reset();
		SAFE_DELETE(iContent)
	}

void CDocXmlParser::Parse(const TDesC8& aBuffer)
	{
	CDefaultDeclHandler *decl = new (ELeave) CDefaultDeclHandler;
	CleanupStack::PushL(decl);

	CSyParser *syParser = CSyParser::NewLC(TPtrC());

	syParser->SetHandler(this);
	syParser->SetHandler(decl);

	syParser->Parse(aBuffer, ETrue);

	CleanupStack::PopAndDestroy(2);

	WriteContent();
	}

void CDocXmlParser::StartElement(const TQualified& aName, const RArray<
		TAttribute>& aAttributes)
	{
	TInt type = ConvertTagToNumber(aName.iLocalName);

	switch (type)
		{
		case EDocXmlTagA:
			ParseTagA(aAttributes);
			break;
		default:
			break;
		}
	PushTag(type);
	}

void CDocXmlParser::EndElement(const TQualified& aName)
	{
	TInt type = ConvertTagToNumber(aName.iLocalName);

	switch (type)
		{
		case EDocXmlTagBr:
		case EDocXmlTagP:
			EndParseTagP();
		default:
			break;
		}
	PopTag();
	}

void CDocXmlParser::CharacterData(const TDesC& aData)
	{
	TInt type = StackTag();
	switch (type)
		{
		case EDocXmlTagP:
			ParseDataP(aData);
			break;
		default:
			break;
		}
	}

//void CDocXmlParser::StartCDataSection()
//	{
//	}
//void CDocXmlParser::EndCDataSection()
//	{
//	}

TInt CDocXmlParser::ConvertTagToNumber(const TDesC& aTag)
	{
	HBufC* tag = aTag.AllocL();
	tag->Des().LowerCase();
	TPtrC ptr = tag->Des();
	TInt re = EDocXmlTagNone;

	if (ptr.Compare(KDocXmlTagP) == 0)
		{
		re = EDocXmlTagP;
		goto _RESULT;
		}

	if (ptr.Compare(KDocXmlTagA) == 0)
		{
		re = EDocXmlTagA;
		goto _RESULT;
		}

	if (ptr.Compare(KDocXmlTagBr) == 0)
		{
		re = EDocXmlTagBr;
		goto _RESULT;
		}

	//	if (ptr.Compare() == 0)
	//		return;

	_RESULT: delete tag;

	return re;
	}

void CDocXmlParser::PushTag(const TInt aTag)
	{
	iTagStack.Append(aTag);
	}

void CDocXmlParser::PopTag()
	{
	TInt index = iTagStack.Count() - 1;
	iTagStack.Remove(index);
	}

TInt CDocXmlParser::StackTag()
	{
	TInt index = iTagStack.Count() - 1;
	if (index >= 0)
		{
		TInt tag = iTagStack[index];
		return tag;
		}
	else
		return -1;
	}

TInt CDocXmlParser::StackParentTag(TInt aLevel)
	{
	TInt index = iTagStack.Count() - aLevel;
	if (index >= 0)
		{
		TInt tag = iTagStack[index];
		return tag;
		}
	else
		return -1;
	}

void CDocXmlParser::EndParseTagP()
	{
	if (iContent)
		{
		TInt len = 2 + iContent->Length();
		iContent = iContent->ReAllocL(len);
		iContent->Des().Append('\n');
		}
	else
		{
//		iContent = HBufC8::New(2);
//		iContent->Des().Append('\n');
		}
	}

void CDocXmlParser::ParseDataP(const TDesC& aData)
	{
	HBufC8* data = CCommonUtils::ConvertToUTF8FromUnicode(aData);
	if (iContent)
		{
		TInt len = data->Length() + iContent->Length();
		iContent = iContent->ReAllocL(len);
		iContent->Des().Append(data->Des());
		}
	else
		{
		iContent = data->AllocL();
		}
	delete data;
	}

void CDocXmlParser::ParseTagA(const RArray<TAttribute>& aAttributes)
	{
	for (TInt i = 0; i < aAttributes.Count(); i++)
		{
		TAttribute attr = aAttributes[i];

		HBufC* name = attr.iName.iLocalName.AllocL();

		TPtr ptrName = name->Des();
		ptrName.LowerCase();

		if (ptrName.Compare(KDocXmlAttrHref) == 0)
			{
			if (iRSSBriefItem)
				iRSSBriefItem->SetMp3(attr.iValue);
			}

		delete name;
		}
	}

void CDocXmlParser::WriteContent()
	{
	TFileName filename;
	CCommonFileUtil::GetDetailDocEFirst(filename, iRSSBriefItem);

	RFile file;

	TInt pos = filename.LocateReverse('\\');
	if (pos != KErrNotFound)
		{
		TPtrC dirName = filename.Left(pos + 1);
		CCoeEnv::Static()->FsSession().MkDirAll(dirName);
		}
	TInt err = file.Replace(CCoeEnv::Static()->FsSession(), filename,
			EFileWrite);
	if (KErrNone != err)
		{
		return;
		}

	CleanupClosePushL(file);

	if (iContent)
		file.Write(iContent->Des());

	CleanupStack::PopAndDestroy();

		SAFE_DELETE(iContent)
	}
